﻿using Newtonsoft.Json.Linq;
using PuppeteerSharp;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;

namespace ZhongKeSite.Common.Helper
{
   public class PuppeteerSharpHelp
    {/// <summary>
     /// Html生成图片
     /// </summary>
     /// <param name="url">html路径</param>
     /// <param name="fileName">文件保存路径</param>
     /// <param name="callback"></param>
     /// <returns></returns>
        public static async Task GenerateImage(string url, string fileName, Action<Page> callback = null)
        {
            try
            {
                await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);

                using (var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true }))
                {
                    using (var page = await browser.NewPageAsync())
                    {

                        #region 参数设置
                        await page.SetViewportAsync(new ViewPortOptions
                        {
                            Width = 1920,
                            Height = 1080
                        });

                        await page.GoToAsync(url, new NavigationOptions
                        {

                        });
                        #endregion

                        #region 回调函数设置页面动态数据
                        callback?.Invoke(page);
                        #endregion

                        #region 滚动翻页

                        // 网页加载最大高度
                        var max_height_px = 20000;

                        // 滚动高度
                        var scrollStep = 1080;
                        var height_limit = false;

                        JObject mValues = JObject.Parse("{\"scrollEnable\": true, \"height_limit\": false}");

                        while (mValues.GetJObectValue<bool>("scrollEnable"))
                        {
                            mValues = (JObject)await page.EvaluateFunctionAsync(@"(scrollStep, max_height_px, height_limit) => {
                                // 防止网页没有body时，滚动报错
                                if (document.scrollingElement)
                                {
                                    var scrollTop = document.scrollingElement.scrollTop;
                                    document.scrollingElement.scrollTop = scrollTop + scrollStep;

                                    if (null != document.body && document.body.clientHeight > max_height_px)
                                    {
                                        height_limit = true;
                                    }
                                    else if (document.scrollingElement.scrollTop + scrollStep > max_height_px)
                                    {
                                        height_limit = true;
                                    }

                                    var scrollEnableFlag = false;
                                    if (null != document.body)
                                    {
                                        scrollEnableFlag = document.body.clientHeight > scrollTop + 1081 && !height_limit;
                                    }
                                    else
                                    {
                                        scrollEnableFlag = document.scrollingElement.scrollTop + scrollStep > scrollTop + 1081 && !height_limit;
                                    }

                                    return {
                                        'scrollEnable': scrollEnableFlag,
                                        'height_limit': height_limit,
                                        'document_scrolling_Element_scrollTop': document.scrollingElement.scrollTop
                                    };
                                }

                            }", scrollStep, max_height_px, height_limit);

                        }

                        #endregion

                        await page.ScreenshotAsync(fileName, new ScreenshotOptions
                        {
                            FullPage = true
                        });
                    }
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex);
                throw ex;
            }
        }

        /// <summary>
        /// html生成pdf
        /// </summary>
        /// <param name="url">html路径</param>
        /// <param name="fileName">文件保存路径</param>
        /// <param name="callback">打开页面后的回调函数</param>
        /// <returns></returns>
        public static async Task GeneratePdf(string url, string fileName, Action<Page> callback = null)
        {

            try
            {
                await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);

                using (var browser = await Puppeteer.LaunchAsync(new LaunchOptions() { Headless = true }))
                {
                    using (var page = await browser.NewPageAsync())
                    {
                        await page.GoToAsync(url, new NavigationOptions
                        {
                            WaitUntil = new WaitUntilNavigation[] { WaitUntilNavigation.DOMContentLoaded }
                        });

                        await page.SetViewportAsync(new ViewPortOptions
                        {
                            Width = 1920,
                            Height = 1080
                        });

                        callback?.Invoke(page);

                        await page.WaitForTimeoutAsync(5000);

                        string directory = Path.GetDirectoryName(fileName);
                        if (!string.IsNullOrWhiteSpace(directory) && !Directory.Exists(directory))
                        {
                            Directory.CreateDirectory(directory);
                        }

                        await page.PdfAsync(fileName, new PdfOptions
                        {
                            Width = 1920,
                            Height = 1080
                        });
                    }
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex);
                throw ex;
            }


            //await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);
            //var browser = await Puppeteer.LaunchAsync(new LaunchOptions
            //{
            //    Headless = true
            //});
            //var page = await browser.NewPageAsync();
            //await page.SetViewportAsync(new ViewPortOptions
            //{
            //    Width = 1920,
            //    Height = 1080
            //});
            //await page.GoToAsync(url);
            //await page.PdfAsync(fileName,new PdfOptions {
            //    Width = 1920,
            //    Height = 1080
            //});
        }


        //速度较慢,但保真度比较好
        public static async Task GeneratePdfFromHtml(string html, string fileName)
        {

            try
            {
                await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);

                using (var browser = await Puppeteer.LaunchAsync(new LaunchOptions() { Headless = true }))
                {
                    using (var page = await browser.NewPageAsync())
                    {
                        //1.
                        await page.SetContentAsync(html);

                        //2.
                        await page.SetViewportAsync(new ViewPortOptions
                        {
                            Width = 1920,
                            Height = 1080
                        });

                        //3.
                        await page.WaitForTimeoutAsync(5000);

                        string directory = Path.GetDirectoryName(fileName);
                        if (!string.IsNullOrWhiteSpace(directory) && !Directory.Exists(directory))
                        {
                            Directory.CreateDirectory(directory);
                        }

                        //4.
                        await page.PdfAsync(fileName, new PdfOptions
                        {
                            Width = 1920,
                            Height = 1080
                        });
                    }
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex);
                throw ex;
            }
        }
    }
}
